package test.demo;


import com.alibaba.fastjson.JSON;
import tech.waterism.modelbase.PredictBase;
import tech.waterism.modelbase.PredictResult;

import java.util.*;

/**
 * 陕北模型
 * @author 初京刚
 * @date 2022-1-7
 * @version 1.0
 */

public class SHANNXI  extends PredictBase {

    /**
     * 流域平均张力水容量（mm）、流域蓄水容量
     */
    private double Wm;

    /**
     * 流域蒸散发折算系数
     */
    private double Kc;

    /**
     * 流域内下渗能力抛物线形状系数
     */
    private double Bx;

    /**
     * 不透水的面积占全流域面积的比
     */
    private double IM;

    /**
     * 流域 月蒸发量（mm）
     */
    private double[] ES;

    /**
     * 流域初始下渗能力，相当于土壤干燥时的下渗能力，平均最大下渗能力，mm/min
     */
    private double f0;

    /**
     * 流域平均稳定下渗能力，mm/min
     */
    private double fc;

    /**
     * 土壤含水计算的允许误差
     */
    private double err_limit;

    /**
     * 下渗能力衰弱系数，随土质而变的系数，1/min
     */
    private double k;

    /**
     * 流域 时段蒸发量（mm）
     */
    private double[] floodE;

    /**
     * 降水时间
     */
    private Date[] floodTm;

    /**
     * 降水量
     */
    private double[] floodDrp;

    /**
     * 降水序列长度
     */
    private Integer floodRainRange;

    /**
     * 降水时段长
     */
    private double timeInterval;

    /**
     * 模拟总产流
     */
    private double[] RunoffSim;

    /**
     * 总产流
     */
    private double[] R;

//    /**
//     * 不透水面积产流
//     */
//    private double[] RIm;

    /**
     * 净雨
     */
    private double[] PE;

    /**
     * 雨强 mm/min
     */
    private double[] PEI;

    /**
     * 张力水含量
     */
    private double[] Ws;

    /**
     * 流域面积
     */
    private double Area;

    /**
     * 径流消退系数
     */
    private double CS;

    /**
     * 子河段洪水波传播时间
     */
    private double KE;

    /**
     * 河段数
     */
    private int N;

    /**
     * 子河段流量比重因子
     */
    private double XE;

    /**
     * 滞时（h）
     */
    private double L;

    /**
     * 坡面汇流-地表径流
     */
    private double[] Q;

    /**
     * 坡面汇流-地表径流状态
     */
    private double[] QS;

    /**
     * 马法初始流量，河段下断面各时段初始流量
     */
    private double[][] QX0;

    /**
     * 初始总基流
     */
    private double[][] QS0;

    /**
     * 马法初始流量，河段下断面初始流量
     */
    private double[] QXInitial;

    /**
     * 初始总基流
     */
    private double[] QSInitial;

    /**
     * 地表径流流量
     */
    private double[] QInitial;

    /**
     * 地表径流流量
     */
    private double qsp;

    /**
     * 流域张力水含量初值（m）
     */
    private double WSInitial;

    /**
     * 下渗曲线选取标志
     */
    private int type;

    /**
     * 菲利普下渗曲线参数
     */
    private double A;

    /**
     * 菲利普下渗曲线参数
     */
    private double B;

    public SHANNXI(Map<String, String> data) {
        super();
        WSInitial = Double.parseDouble(data.get("WSIG"));
        QSInitial = JSON.parseObject(data.get("QSIG"), double[].class);
        QXInitial = JSON.parseObject(data.get("QXSIG"), double[].class);
        qsp = Double.parseDouble(data.get("QSP"));
        QInitial = new double[]{qsp};
        Kc = Double.parseDouble(data.get("KC"));
        Bx = Double.parseDouble(data.get("BX"));
        IM = Double.parseDouble(data.get("IM"));
        Area = Double.parseDouble(data.get("F"));
        CS = Double.parseDouble(data.get("CS"));
        L = Double.parseDouble(data.get("LAG"));
        KE = Double.parseDouble(data.get("KK"));
        XE = Double.parseDouble(data.get("X"));
        N = Integer.parseInt(data.get("MP"));
        type = Integer.parseInt(data.get("TYPE"));
        err_limit = Double.parseDouble(data.get("ERLMT"));
        A = Double.parseDouble(data.get("A"));
        B = Double.parseDouble(data.get("B"));
        ES = JSON.parseObject(data.get("ES"), double[].class);
        floodTm = JSON.parseObject(data.get("dt"), Date[].class);// input[i].data.dt
        floodDrp = JSON.parseObject(data.get("rain"), double[].class);// input[i].data.rain
        floodE = JSON.parseObject(data.get("evaporation"), double[].class);  // input[i].data.evaporation
        floodRainRange = floodDrp.length;
        timeInterval = Double.parseDouble(data.get("clen"));                  // index.clen
        f0 = Double.parseDouble(data.get("F0"));
        fc = Double.parseDouble(data.get("FC"));
        k = Double.parseDouble(data.get("K"));
        Wm = f0 / k;
        RunoffSim = new double[floodRainRange];
        R = new double[floodRainRange];
//        RIm = new double[floodRainRange];
        PE = new double[floodRainRange];
        PEI = new double[floodRainRange];
        QS = new double[floodRainRange + 1];
        Q = new double[floodRainRange];
    }

    /**
     * 模型计算
     */
    public Map<String, double[]> SHANNXImodel() {

        // 超渗产流
        expinfMechanism();

        for (Integer j = 0; j < floodRainRange; j++) {
//            RunoffSim[j] = RS[j] + RIm[j] + RI[j] + RG[j];
            RunoffSim[j] = R[j];
        }

        // 坡面汇流-线性水库
        LinerReservoir();

        double[] Qtmp = new double[floodRainRange];//单元面积河网总入流（m3/s）

        for (Integer j = 0; j < floodRainRange; j++) {
            Qtmp[j] = Q[j];
            if (Qtmp[j] < 0.0) {
                Qtmp[j] = 0.0;
            }
        }

        //河网汇流-滞后演算法,单元面积出口流量（m3/s）
        double[] Qf = TimeLag(Qtmp);

        // 河道演进
        double[] QSim = muskingum(Qf);

        Map<String, double[]> simulationResult = new HashMap<>();
        simulationResult.put("rain", floodDrp);
        simulationResult.put("PE", PE);
        simulationResult.put("runoffSim", RunoffSim);
        simulationResult.put("R", R);
//        simulationResult.put("RIM", RIm);
        simulationResult.put("Q", Q);
        simulationResult.put("QSim", QSim);

        return simulationResult;
    }

    /**
     * 蒸发计算
     *
     * @param date   降水时间
     * @param timeIn 时间间隔 (h)
     * @return 蒸发
     */
    private double calcEvaporationPotential(Date date, double timeIn) {
        Calendar time = Calendar.getInstance();
        time.setTime(date);
        Integer Month = time.get(Calendar.MONTH) + 1; // 获得降雨开始月份
        double Ep = ES[Month - 1]/30; // 月蒸发量转换成日蒸发量
        Ep = Ep * timeIn / 24; // 日蒸发量转换成时段蒸发量
        return Ep;
    }

    /**
     * 超渗产流模型
     *
     * @return 总产流
     */
    private void expinfMechanism() {

        Ws = new double[floodRainRange + 1]; // 张力水蓄量，随时段变化
        Ws[0] = WSInitial;

        double EPt; // EPt为蒸散发，等于Kc * E（实测蒸发，即ES[]或时段）
        double Ft0 = 0.0; // 时段初流域下渗能力
        double Ft = 0.0; //时段下渗量
        double fmm;

        for(Integer i = 0; i < floodRainRange; i++) {

            //蒸发计算
            if (floodE == null || floodE.length != floodRainRange) {
                EPt = Kc * calcEvaporationPotential(floodTm[i], timeInterval);
            } else {
                EPt = Kc * floodE[i];
            }

            // PE[i]为降雨减去蒸发，可正可负
            PE[i] = floodDrp[i] - EPt;
            PEI[i] = PE[i] / (60 * timeInterval);

            if (type == 0) {
                //霍顿下渗曲线<霍顿与菲利蒲下渗公式对子洲径流站资料的拟合>
                Ft0 = HortonInfil(Ws[i]);
                // 计算流域该时段的最大点下渗能力<格林一安普特下渗曲线的改进和应用>、<格林－安普特降雨径流模型改进及初步应用>
                fmm = Ft0 * (1 + Bx) / (1 - IM);
                if (PEI[i] > fmm) {
                    // 全流域产流
                    /*Ws[i + 1] = fc * 60 * timeInterval * (i + 1) + 1 / k * (f0 - fc) * (1 - Math.exp(-k * 60 * timeInterval * (i + 1)));
                    if(Ws[i + 1] > Wm){
                        Ws[i + 1] = Wm;
                    }
                    Ft = Ws[i + 1] - Ws[i];*/

                    Ft = Ft0 * 60 * timeInterval;
                    Ws[i + 1] = Ws[i] + Ft;
                    if(Ft < 0){
                        Ft = 0;
                    }
                    if(Ws[i + 1] > Wm){
                        Ws[i + 1] = Wm;
                    }
                    if(Ws[i + 1] < 0){
                        Ws[i + 1] = 0;
                    }
                    R[i] = PE[i] - Ft;
                    if(R[i] < 0){
                        R[i] = 0;
                    }

                } else {
                    R[i] = (PEI[i] - Ft0 + Ft0 * Math.pow(1 - PEI[i] / fmm, Bx + 1)) * 60 * timeInterval;
                    if(R[i] < 0){
                        R[i] = 0;
                    }
                    Ws[i + 1] = Ws[i] + PE[i] - R[i];
                    if(Ws[i + 1] > Wm){
                        Ws[i + 1] = Wm;
                    }
                    if(Ws[i + 1] < 0){
                        Ws[i + 1] = 0;
                    }
                }
            } else if (this.type == 1) {
                //菲利普斯下渗曲线<霍顿与菲利蒲下渗公式对子洲径流站资料的拟合>
                if(Ws[i] > 0) {
                    Ft0 = PhillipsInfli(Ws[i]);
                } else {
                    Ft0 = PhillipsInfli(0.1);
                }
                // 计算流域该时段的最大点下渗能力<格林一安普特下渗曲线的改进和应用>、<格林－安普特降雨径流模型改进及初步应用>
                fmm = Ft0 * (1 + Bx) / (1 - IM);
                if (PEI[i] > fmm) {
                    // 全流域产流
                    R[i] = (PEI[i] - Ft0) * 60 * timeInterval;
                    if(R[i] < 0){
                        R[i] = 0;
                    }
                    Ws[i + 1] = Ws[i] + Ft0 * 60 * timeInterval;
                    if(Ws[i + 1] > Wm){
                        Ws[i + 1] = Wm;
                    }
                } else {
                    R[i] = (PEI[i] - Ft0 + Ft0 * Math.pow(1 - PEI[i] / fmm, Bx + 1)) * 60 * timeInterval;
                    if(R[i] < 0){
                        R[i] = 0;
                    }
                    Ws[i + 1] = Ws[i] + PE[i] - R[i];
                    if(Ws[i + 1] > Wm){
                        Ws[i + 1] = Wm;
                    }
                    if(Ws[i + 1] < 0){
                        Ws[i + 1] = 0;
                    }
                }
            }
        }
    }

    /**
     * 菲利普斯下渗曲线计算
     *
     * @param w0          时段初土壤含水
     * @return 下渗能力
     */
    private double PhillipsInfli(double w0) {
        return B * B * (1 + Math.sqrt(1 + 4 * A * w0 / (B * B))) / (4 * w0) + A;
    }

    /**
     * 霍顿下渗曲线计算
     *
     * @param w0          时段初土壤含水
     * @return 下渗能力
     */
    private double HortonInfil(double w0) {

        /*
            理论基础：<流域水文模型-新安江模型和陕北模型>pdf66页
            数学基础：迭代求解
        */
        // 由经验初设模型参数
        double T = w0 / f0;

        double w0ByCount = fc * T + 1 / k * (f0 - fc) * (1 - Math.exp(-k * T));
        double fByCount = 0.0;
        while (Math.abs(w0 - w0ByCount) > err_limit) {
            fByCount = f0 - k * (w0ByCount - fc * T);
//            fByCount = fc + (f0 - fc) * Math.exp(-k * T);
            T = T + (w0 - w0ByCount) / fByCount;
            w0ByCount = fc * T + 1 / k * (f0 - fc) * (1 - Math.exp(-k * T));
        }
        fByCount = f0 - k * (w0 - fc * T);
        return fByCount;
    }

    /**
     * 坡面汇流
     * 线性水库地面径流
     *
     * @return 地表、壤中流、地下径流汇流
     */

    private void LinerReservoir() {
        double U = Area / (3.6 * timeInterval); //R 单位转换系数（km2/h = 1000000 m2/ 3600 s = 1000m2/3.6s，km2·mm/h = 1000000 * 0.001 m3/ 3600 s = m3/3.6s）

//        // 参数CI和CG通常以日尺度定义，需要转换为时段尺度
//        double D = 24 / timeInterval;
        /*double CID = Math.pow(CI,1.0/D);
        double CGD = Math.pow(CG,1.0/D);*/

        /*
        QS[0] = (RS[0] + RIm[0]) * (1 - CS) * U;
        QI[0] = RI[0] * (1 - CI) * U;
        QG[0] = RG[0] * (1 - CG) * U;
        */

//        // 新增逻辑
//        QS[0] = (RS[0] + RIm[0]) * U;
        Q[0] = R[0] * U;
//        QI[0] = qip + RI[0] * (1 - CID) * U;
//        QG[0] = qgp + RG[0] * (1 - CGD) * U;
        QS[0] = qsp;
//        QIS0[0] = qip;
//        QGS0[0] = qgp;
//        QS[0] = qsp;
//        QI[0] = qip;
//        QG[0] = qgp;

        for (Integer i = 1; i < floodRainRange; i++) {
//            QS[i] = QS[i - 1] * CS + (RS[i] + RIm[i]) * (1 - CS) * U;
            Q[i] = R[i] * U;
            /*QI[i] = QI[i - 1] * CID + RI[i] * (1 - CID) * U;
            QG[i] = QG[i - 1] * CGD + RG[i] * (1 - CGD) * U;*/
            QS[i] = Q[i - 1];
            /*QIS0[i] = QI[i - 1];
            QGS0[i] = QG[i - 1];*/
        }

        QS[floodRainRange] = Q[floodRainRange - 1];
        /*QIS0[floodRainRange] = QI[floodRainRange - 1];
        QGS0[floodRainRange] = QG[floodRainRange - 1];*/

//        for (Integer i = 1; i < floodRainRange; i++) {
////            QS[i] = QS[i - 1] * CS + (RS[i] + RIm[i]) * (1 - CS) * U;
//            QS[i] = (RS[i] + RIm[i]) * U;
//            QI[i] = QI[i - 1] * CID + RI[i] * (1 - CID) * U;
//            QG[i] = QG[i - 1] * CGD + RG[i] * (1 - CGD) * U;
//        }
    }

    /**
     * 河网汇流-滞时
     * 滞后演算法
     *
     * @param Q 单元面积河网总入流
     * @return 河网汇流-单元面积出口流量（m3/s）
     */
    private double[] TimeLag(double[] Q) {

        double[] Qf = new double[Q.length];
        Integer T = Integer.valueOf((int) L);
        if (T <= 0) {
            T = 0;
            for (Integer i = 0; i < Q.length; i++) {
                if (i == 0) {
//                    Qf[0] = (1 - CS) * Q[0];
                    Qf[i] = QSInitial[0];
                } else {
                    Qf[i] = CS * Qf[i - 1] + (1 - CS) * Q[i];
                }
            }
        } else {
            for (Integer i = 0; i < Q.length; i++) {
                /*
                if (i == 0) {
                    Qf[0] = 0.0;
                } else if (i < T) {
                    Qf[i] = CS * Qf[i - 1];
                    */
                if(i < T) {
                    if(i < Qf.length) {
                        if(i < QSInitial.length) {
                            Qf[i] = QSInitial[i];
                        } else {
                            Qf[i] = Qf[i - 1];
                        }
                    }
                } else {
                    Qf[i] = CS * Qf[i - 1] + (1 - CS) * Q[i - T];
                }
            }
        }

        // 新增逻辑:存储每一步的初值
        QS0 = new double[Q.length + 1][QSInitial.length];
        for (int i = 0; i < QSInitial.length; i++) {
            QS0[0][i] = QSInitial[i];
        }
        for (int i = 1; i < Q.length; i++) {
            if (i < QSInitial.length) {
                for (int j = 0; j < QSInitial.length; j++) {
                    if(i + j < QSInitial.length) {
                        QS0[i][j] = QSInitial[j + i];
                    } else {
                        QS0[i][j] = Q[(i + j) -QSInitial.length];
                    }
                }
            } else {
                for (int j = 0; j < QSInitial.length; j++) {
                    QS0[i][j] = Q[i - QSInitial.length + j];
                }
            }
        }

//        QS0 = new double[Q.length][QSInitial.length];
//        for(Integer i = 0; i < Q.length; i++){
//            for(Integer j = 0; j < QSInitial.length; j++){
//                if(i + j < Q.length){
//                    QS0[i][j] = Q[i + j];
//                }else{
//                    QS0[i][j] = QS0[i][j - 1];
//                }
//            }
//        }

        return Qf;
    }

    /**
     * 河道演进-分段马斯京根
     *
     * @param Qr 河网汇流-单元面积出口流量（m3/s）
     * @return 河道演进-单元面积出口流量（m3/s）
     */
    private double[] muskingum(double[] Qr) {
        //double[] QC = new double[Qr.length];
        double[] QC = new double[N];//河段下断面时段初始流量
        double[] QRouting = new double[Qr.length];//河道演进结果
        QX0 = new double[Qr.length + 1][N]; // 新增逻辑:存储每一步的初值
        for(Integer j = 0; j < N; j++){
            if(j < QXInitial.length){
                QC[j] = QXInitial[j];
            }else{
                QC[j] = QC[j - 1];
            }
            QX0[0][j] = QC[j];
        }

        double CD = 0.5 * timeInterval + KE - KE * XE;
        double C0 = (0.5 * timeInterval - KE * XE) / CD;
        double C1 = (0.5 * timeInterval + KE * XE) / CD;
        double C2 = 1 - C0 - C1;

        double QI1 = 0, QI2 = 0, QO1 = 0, QO2 = 0;//河段上、下断面时段初始流量和时段末流量
        if (C0 >= 0.0 && C2 >= 0.0) {// C0和C2需大于等于0，才满足马斯京根法的适用条件
            for (Integer i = 0; i < Qr.length; i++) {
                if(i == 0) {
                    QI1 = Qr[i];
                } else {
                    QI1 = Qr[i - 1];
                }
                QI2 = Qr[i];

                // 分段计算
                if(N > 0) {
                    for(Integer j = 0; j < N; j++){
                        QX0[i][j] = QC[j];// 新增逻辑:存储每一步的初值
                        QO1 = QC[j];
                        QO2 = C0 * QI2 + C1 * QI1 + C2 * QO1;
                        QI1 = QO1;
                        QI2 = QO2;
                        QC[j] = QO2;
                    }
                } else {
                    // 新增逻辑:存储每一步的初值
                    QX0[i] = QXInitial;

                    QO2 = Qr[i];
                }

                /*
                if (i != 0) {
                    QC[i] = C0 * Qr[i] + C1 * Qr[i - 1] + C2 * QC[i - 1];
                } else {
                    QC[i] = Qr[i];
                }
                 */

                if (QO2 < 0.0001f)
                    QO2 = 0.0f;
                QRouting[i] = QO2;
            }

            for (Integer j = 0; j < N; j++) {
                QX0[Qr.length][j] = QC[j];
            }

        } else {// 否则，就不考虑河道演进了
            System.arraycopy(Qr, 0, QRouting, 0, Qr.length);
        }

        return QRouting;
    }

    private List<String> toStringList(double[] array0){
        String[] array = new String[array0.length];
        for(int i = 0; i < array.length; i++){
            array[i] = String.valueOf(array0[i]);
        }
        return Arrays.asList(array);
    }

    private List<String> toStringList(double[][] array0){
        String[] array = new String[array0.length];
        for(int i = 0; i < array.length; i++){
            array[i] = Arrays.toString(array0[i]);
        }
        return Arrays.asList(array);
    }

    @Override
    public void init() {

    }

    @Override
    public PredictResult predict() {
        PredictResult result = new PredictResult();
        Map<String, double[]> map = SHANNXImodel();

        double[][] RSim = new double[1][];
        //总产流
        RSim[0] = map.get("R");
//        //流域地表产流
//        RSim[1] = map.get("RS");
//        //流域土壤产流
//        RSim[2] = map.get("RI");
//        //流域地下产流
//        RSim[3] = map.get("RG");

        //流域面积总产流
        result.setRunoffSim(map.get("runoffSim"));
        result.setRSim(RSim);
        //河道演进结果
        result.setQSim(map.get("QSim"));

        // 更新状态
        List<String> WS = toStringList(Ws);
//        List<String> WUP = toStringList(Wu);
//        List<String> WLP = toStringList(Wl);
//        List<String> WDP = toStringList(Wd);
//        List<String> SP = toStringList(S);
//        List<String> FRP = toStringList(FR);
        List<String> QXSIG = toStringList(QX0);
        List<String> QSIG = toStringList(QS0);
        List<String> QSP = toStringList(QS);
//        List<String> QIP = toStringList(QIS0);
//        List<String> QGP = toStringList(QGS0);
//        List<String> QSP = toStringList(QS);
//        List<String> QIP = toStringList(QI);
//        List<String> QGP = toStringList(QG);
        Map<String, List<String>> status = new HashMap<>();
        //土壤含水量
        status.put("WS", WS);
//        //上层张力水含量
//        status.put("WUP", WUP);
//        //下层张力水含量
//        status.put("WLP", WLP);
//        //深层张力水含量
//        status.put("WDP", WDP);
//        //产流面积自由水深
//        status.put("SP", SP);
//        //产流面积系数
//        status.put("FRP", FRP);
        //河段下断面各时段初始流量
        status.put("QXSIG", QXSIG);
        //各时段初始总基流
        status.put("QSIG", QSIG);
        //地表坡面汇流
        status.put("QSP", QSP);
//        //坡面汇流-壤中流
//        status.put("QIP", QIP);
//        //地下坡面汇流
//        status.put("QGP", QGP);
        result.setNewStatus(status);

        return result;

        //return null;
    }

    public static void main(String[] args) {
        String a = "{\"A\":\"0.6278196633328212\",\"B\":\"2.9354660358905718\",\"F\":\"4235.0240256\",\"K\":\"0.04235707139378653\",\"dt\":\"[\\\"2020-05-31 08:00:00\\\",\\\"2020-05-31 14:00:00\\\",\\\"2020-05-31 20:00:00\\\",\\\"2020-06-01 02:00:00\\\",\\\"2020-06-01 08:00:00\\\",\\\"2020-06-01 14:00:00\\\",\\\"2020-06-01 20:00:00\\\",\\\"2020-06-02 02:00:00\\\",\\\"2020-06-02 08:00:00\\\",\\\"2020-06-02 14:00:00\\\",\\\"2020-06-02 20:00:00\\\",\\\"2020-06-03 02:00:00\\\",\\\"2020-06-03 08:00:00\\\",\\\"2020-06-03 14:00:00\\\",\\\"2020-06-03 20:00:00\\\",\\\"2020-06-04 02:00:00\\\",\\\"2020-06-04 08:00:00\\\",\\\"2020-06-04 14:00:00\\\",\\\"2020-06-04 20:00:00\\\",\\\"2020-06-05 02:00:00\\\",\\\"2020-06-05 08:00:00\\\",\\\"2020-06-05 14:00:00\\\",\\\"2020-06-05 20:00:00\\\",\\\"2020-06-06 02:00:00\\\",\\\"2020-06-06 08:00:00\\\",\\\"2020-06-06 14:00:00\\\",\\\"2020-06-06 20:00:00\\\",\\\"2020-06-07 02:00:00\\\",\\\"2020-06-07 08:00:00\\\",\\\"2020-06-07 14:00:00\\\",\\\"2020-06-07 20:00:00\\\",\\\"2020-06-08 02:00:00\\\",\\\"2020-06-08 08:00:00\\\",\\\"2020-06-08 14:00:00\\\",\\\"2020-06-08 20:00:00\\\",\\\"2020-06-09 02:00:00\\\",\\\"2020-06-09 08:00:00\\\",\\\"2020-06-09 14:00:00\\\",\\\"2020-06-09 20:00:00\\\",\\\"2020-06-10 02:00:00\\\",\\\"2020-06-10 08:00:00\\\",\\\"2020-06-10 14:00:00\\\",\\\"2020-06-10 20:00:00\\\",\\\"2020-06-11 02:00:00\\\",\\\"2020-06-11 08:00:00\\\",\\\"2020-06-11 14:00:00\\\",\\\"2020-06-11 20:00:00\\\",\\\"2020-06-12 02:00:00\\\",\\\"2020-06-12 08:00:00\\\",\\\"2020-06-12 14:00:00\\\",\\\"2020-06-12 20:00:00\\\",\\\"2020-06-13 02:00:00\\\",\\\"2020-06-13 08:00:00\\\",\\\"2020-06-13 14:00:00\\\",\\\"2020-06-13 20:00:00\\\",\\\"2020-06-14 02:00:00\\\",\\\"2020-06-14 08:00:00\\\",\\\"2020-06-14 14:00:00\\\",\\\"2020-06-14 20:00:00\\\",\\\"2020-06-15 02:00:00\\\",\\\"2020-06-15 08:00:00\\\",\\\"2020-06-15 14:00:00\\\",\\\"2020-06-15 20:00:00\\\",\\\"2020-06-16 02:00:00\\\",\\\"2020-06-16 08:00:00\\\",\\\"2020-06-16 14:00:00\\\",\\\"2020-06-16 20:00:00\\\",\\\"2020-06-17 02:00:00\\\",\\\"2020-06-17 08:00:00\\\",\\\"2020-06-17 14:00:00\\\",\\\"2020-06-17 20:00:00\\\",\\\"2020-06-18 02:00:00\\\",\\\"2020-06-18 08:00:00\\\",\\\"2020-06-18 14:00:00\\\",\\\"2020-06-18 20:00:00\\\",\\\"2020-06-19 02:00:00\\\",\\\"2020-06-19 08:00:00\\\",\\\"2020-06-19 14:00:00\\\",\\\"2020-06-19 20:00:00\\\",\\\"2020-06-20 02:00:00\\\",\\\"2020-06-20 08:00:00\\\",\\\"2020-06-20 14:00:00\\\",\\\"2020-06-20 20:00:00\\\",\\\"2020-06-21 02:00:00\\\",\\\"2020-06-21 08:00:00\\\",\\\"2020-06-21 14:00:00\\\",\\\"2020-06-21 20:00:00\\\",\\\"2020-06-22 02:00:00\\\",\\\"2020-06-22 08:00:00\\\",\\\"2020-06-22 14:00:00\\\",\\\"2020-06-22 20:00:00\\\",\\\"2020-06-23 02:00:00\\\",\\\"2020-06-23 08:00:00\\\",\\\"2020-06-23 14:00:00\\\",\\\"2020-06-23 20:00:00\\\",\\\"2020-06-24 02:00:00\\\",\\\"2020-06-24 08:00:00\\\",\\\"2020-06-24 14:00:00\\\",\\\"2020-06-24 20:00:00\\\",\\\"2020-06-25 02:00:00\\\",\\\"2020-06-25 08:00:00\\\",\\\"2020-06-25 14:00:00\\\",\\\"2020-06-25 20:00:00\\\",\\\"2020-06-26 02:00:00\\\",\\\"2020-06-26 08:00:00\\\",\\\"2020-06-26 14:00:00\\\",\\\"2020-06-26 20:00:00\\\",\\\"2020-06-27 02:00:00\\\",\\\"2020-06-27 08:00:00\\\",\\\"2020-06-27 14:00:00\\\",\\\"2020-06-27 20:00:00\\\",\\\"2020-06-28 02:00:00\\\",\\\"2020-06-28 08:00:00\\\",\\\"2020-06-28 14:00:00\\\",\\\"2020-06-28 20:00:00\\\",\\\"2020-06-29 02:00:00\\\",\\\"2020-06-29 08:00:00\\\",\\\"2020-06-29 14:00:00\\\",\\\"2020-06-29 20:00:00\\\",\\\"2020-06-30 02:00:00\\\",\\\"2020-06-30 08:00:00\\\",\\\"2020-06-30 14:00:00\\\",\\\"2020-06-30 20:00:00\\\",\\\"2020-07-01 02:00:00\\\",\\\"2020-07-01 08:00:00\\\",\\\"2020-07-01 14:00:00\\\",\\\"2020-07-01 20:00:00\\\",\\\"2020-07-02 02:00:00\\\",\\\"2020-07-02 08:00:00\\\",\\\"2020-07-02 14:00:00\\\",\\\"2020-07-02 20:00:00\\\",\\\"2020-07-03 02:00:00\\\",\\\"2020-07-03 08:00:00\\\",\\\"2020-07-03 14:00:00\\\",\\\"2020-07-03 20:00:00\\\",\\\"2020-07-04 02:00:00\\\",\\\"2020-07-04 08:00:00\\\",\\\"2020-07-04 14:00:00\\\",\\\"2020-07-04 20:00:00\\\",\\\"2020-07-05 02:00:00\\\",\\\"2020-07-05 08:00:00\\\",\\\"2020-07-05 14:00:00\\\",\\\"2020-07-05 20:00:00\\\",\\\"2020-07-06 02:00:00\\\",\\\"2020-07-06 08:00:00\\\",\\\"2020-07-06 14:00:00\\\",\\\"2020-07-06 20:00:00\\\",\\\"2020-07-07 02:00:00\\\",\\\"2020-07-07 08:00:00\\\",\\\"2020-07-07 14:00:00\\\",\\\"2020-07-07 20:00:00\\\",\\\"2020-07-08 02:00:00\\\",\\\"2020-07-08 08:00:00\\\",\\\"2020-07-08 14:00:00\\\",\\\"2020-07-08 20:00:00\\\",\\\"2020-07-09 02:00:00\\\",\\\"2020-07-09 08:00:00\\\",\\\"2020-07-09 14:00:00\\\",\\\"2020-07-09 20:00:00\\\",\\\"2020-07-10 02:00:00\\\",\\\"2020-07-10 08:00:00\\\",\\\"2020-07-10 14:00:00\\\",\\\"2020-07-10 20:00:00\\\",\\\"2020-07-11 02:00:00\\\",\\\"2020-07-11 08:00:00\\\",\\\"2020-07-11 14:00:00\\\",\\\"2020-07-11 20:00:00\\\",\\\"2020-07-12 02:00:00\\\",\\\"2020-07-12 08:00:00\\\",\\\"2020-07-12 14:00:00\\\",\\\"2020-07-12 20:00:00\\\",\\\"2020-07-13 02:00:00\\\",\\\"2020-07-13 08:00:00\\\",\\\"2020-07-13 14:00:00\\\",\\\"2020-07-13 20:00:00\\\",\\\"2020-07-14 02:00:00\\\",\\\"2020-07-14 08:00:00\\\",\\\"2020-07-14 14:00:00\\\",\\\"2020-07-14 20:00:00\\\",\\\"2020-07-15 02:00:00\\\",\\\"2020-07-15 08:00:00\\\",\\\"2020-07-15 14:00:00\\\",\\\"2020-07-15 20:00:00\\\",\\\"2020-07-16 02:00:00\\\",\\\"2020-07-16 08:00:00\\\",\\\"2020-07-16 14:00:00\\\",\\\"2020-07-16 20:00:00\\\",\\\"2020-07-17 02:00:00\\\",\\\"2020-07-17 08:00:00\\\",\\\"2020-07-17 14:00:00\\\",\\\"2020-07-17 20:00:00\\\",\\\"2020-07-18 02:00:00\\\",\\\"2020-07-18 08:00:00\\\",\\\"2020-07-18 14:00:00\\\",\\\"2020-07-18 20:00:00\\\",\\\"2020-07-19 02:00:00\\\",\\\"2020-07-19 08:00:00\\\",\\\"2020-07-19 14:00:00\\\",\\\"2020-07-19 20:00:00\\\",\\\"2020-07-20 02:00:00\\\",\\\"2020-07-20 08:00:00\\\",\\\"2020-07-20 14:00:00\\\",\\\"2020-07-20 20:00:00\\\",\\\"2020-07-21 02:00:00\\\",\\\"2020-07-21 08:00:00\\\",\\\"2020-07-21 14:00:00\\\",\\\"2020-07-21 20:00:00\\\",\\\"2020-07-22 02:00:00\\\",\\\"2020-07-22 08:00:00\\\",\\\"2020-07-22 14:00:00\\\",\\\"2020-07-22 20:00:00\\\",\\\"2020-07-23 02:00:00\\\",\\\"2020-07-23 08:00:00\\\",\\\"2020-07-23 14:00:00\\\",\\\"2020-07-23 20:00:00\\\",\\\"2020-07-24 02:00:00\\\",\\\"2020-07-24 08:00:00\\\",\\\"2020-07-24 14:00:00\\\",\\\"2020-07-24 20:00:00\\\",\\\"2020-07-25 02:00:00\\\",\\\"2020-07-25 08:00:00\\\",\\\"2020-07-25 14:00:00\\\",\\\"2020-07-25 20:00:00\\\",\\\"2020-07-26 02:00:00\\\",\\\"2020-07-26 08:00:00\\\",\\\"2020-07-26 14:00:00\\\",\\\"2020-07-26 20:00:00\\\",\\\"2020-07-27 02:00:00\\\",\\\"2020-07-27 08:00:00\\\",\\\"2020-07-27 14:00:00\\\",\\\"2020-07-27 20:00:00\\\",\\\"2020-07-28 02:00:00\\\",\\\"2020-07-28 08:00:00\\\",\\\"2020-07-28 14:00:00\\\",\\\"2020-07-28 20:00:00\\\",\\\"2020-07-29 02:00:00\\\",\\\"2020-07-29 08:00:00\\\",\\\"2020-07-29 14:00:00\\\",\\\"2020-07-29 20:00:00\\\",\\\"2020-07-30 02:00:00\\\",\\\"2020-07-30 08:00:00\\\",\\\"2020-07-30 14:00:00\\\",\\\"2020-07-30 20:00:00\\\",\\\"2020-07-31 02:00:00\\\",\\\"2020-07-31 08:00:00\\\",\\\"2020-07-31 14:00:00\\\",\\\"2020-07-31 20:00:00\\\",\\\"2020-08-01 02:00:00\\\",\\\"2020-08-01 08:00:00\\\",\\\"2020-08-01 14:00:00\\\",\\\"2020-08-01 20:00:00\\\",\\\"2020-08-02 02:00:00\\\",\\\"2020-08-02 08:00:00\\\",\\\"2020-08-02 14:00:00\\\",\\\"2020-08-02 20:00:00\\\",\\\"2020-08-03 02:00:00\\\",\\\"2020-08-03 08:00:00\\\",\\\"2020-08-03 14:00:00\\\",\\\"2020-08-03 20:00:00\\\",\\\"2020-08-04 02:00:00\\\",\\\"2020-08-04 08:00:00\\\",\\\"2020-08-04 14:00:00\\\",\\\"2020-08-04 20:00:00\\\",\\\"2020-08-05 02:00:00\\\",\\\"2020-08-05 08:00:00\\\",\\\"2020-08-05 14:00:00\\\",\\\"2020-08-05 20:00:00\\\",\\\"2020-08-06 02:00:00\\\",\\\"2020-08-06 08:00:00\\\",\\\"2020-08-06 14:00:00\\\",\\\"2020-08-06 20:00:00\\\",\\\"2020-08-07 02:00:00\\\",\\\"2020-08-07 08:00:00\\\",\\\"2020-08-07 14:00:00\\\",\\\"2020-08-07 20:00:00\\\",\\\"2020-08-08 02:00:00\\\",\\\"2020-08-08 08:00:00\\\",\\\"2020-08-08 14:00:00\\\",\\\"2020-08-08 20:00:00\\\",\\\"2020-08-09 02:00:00\\\",\\\"2020-08-09 08:00:00\\\",\\\"2020-08-09 14:00:00\\\",\\\"2020-08-09 20:00:00\\\",\\\"2020-08-10 02:00:00\\\",\\\"2020-08-10 08:00:00\\\",\\\"2020-08-10 14:00:00\\\",\\\"2020-08-10 20:00:00\\\",\\\"2020-08-11 02:00:00\\\",\\\"2020-08-11 08:00:00\\\",\\\"2020-08-11 14:00:00\\\",\\\"2020-08-11 20:00:00\\\",\\\"2020-08-12 02:00:00\\\",\\\"2020-08-12 08:00:00\\\",\\\"2020-08-12 14:00:00\\\",\\\"2020-08-12 20:00:00\\\",\\\"2020-08-13 02:00:00\\\",\\\"2020-08-13 08:00:00\\\",\\\"2020-08-13 14:00:00\\\",\\\"2020-08-13 20:00:00\\\",\\\"2020-08-14 02:00:00\\\",\\\"2020-08-14 08:00:00\\\",\\\"2020-08-14 14:00:00\\\",\\\"2020-08-14 20:00:00\\\",\\\"2020-08-15 02:00:00\\\",\\\"2020-08-15 08:00:00\\\",\\\"2020-08-15 14:00:00\\\",\\\"2020-08-15 20:00:00\\\",\\\"2020-08-16 02:00:00\\\",\\\"2020-08-16 08:00:00\\\",\\\"2020-08-16 14:00:00\\\",\\\"2020-08-16 20:00:00\\\",\\\"2020-08-17 02:00:00\\\",\\\"2020-08-17 08:00:00\\\",\\\"2020-08-17 14:00:00\\\",\\\"2020-08-17 20:00:00\\\",\\\"2020-08-18 02:00:00\\\",\\\"2020-08-18 08:00:00\\\",\\\"2020-08-18 14:00:00\\\",\\\"2020-08-18 20:00:00\\\",\\\"2020-08-19 02:00:00\\\",\\\"2020-08-19 08:00:00\\\",\\\"2020-08-19 14:00:00\\\",\\\"2020-08-19 20:00:00\\\",\\\"2020-08-20 02:00:00\\\",\\\"2020-08-20 08:00:00\\\",\\\"2020-08-20 14:00:00\\\",\\\"2020-08-20 20:00:00\\\",\\\"2020-08-21 02:00:00\\\",\\\"2020-08-21 08:00:00\\\",\\\"2020-08-21 14:00:00\\\",\\\"2020-08-21 20:00:00\\\",\\\"2020-08-22 02:00:00\\\",\\\"2020-08-22 08:00:00\\\",\\\"2020-08-22 14:00:00\\\",\\\"2020-08-22 20:00:00\\\",\\\"2020-08-23 02:00:00\\\",\\\"2020-08-23 08:00:00\\\",\\\"2020-08-23 14:00:00\\\",\\\"2020-08-23 20:00:00\\\",\\\"2020-08-24 02:00:00\\\",\\\"2020-08-24 08:00:00\\\",\\\"2020-08-24 14:00:00\\\",\\\"2020-08-24 20:00:00\\\",\\\"2020-08-25 02:00:00\\\",\\\"2020-08-25 08:00:00\\\",\\\"2020-08-25 14:00:00\\\",\\\"2020-08-25 20:00:00\\\",\\\"2020-08-26 02:00:00\\\",\\\"2020-08-26 08:00:00\\\",\\\"2020-08-26 14:00:00\\\",\\\"2020-08-26 20:00:00\\\",\\\"2020-08-27 02:00:00\\\",\\\"2020-08-27 08:00:00\\\",\\\"2020-08-27 14:00:00\\\",\\\"2020-08-27 20:00:00\\\",\\\"2020-08-28 02:00:00\\\",\\\"2020-08-28 08:00:00\\\",\\\"2020-08-28 14:00:00\\\",\\\"2020-08-28 20:00:00\\\",\\\"2020-08-29 02:00:00\\\",\\\"2020-08-29 08:00:00\\\"]\",\"WSIG\":\"0.0\",\"ERLMT\":\"0.5\",\"BX\":\"0.1630140108588788\",\"KC\":\"1.2924855067479952\",\"X\":\"-0.8046082571340087\",\"TYPE\":\"0\",\"KK\":\"6\",\"rain\":\"[0.22628205128205134,4.708974382051281,7.614102505128206,2.406410276923076,0.5166666666666668,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.010256410256410256,0.5589743615384615,1.3664283846153845E-17,1.3664283846153845E-17,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.005128205128205128,0.016025641025641024,0.016025641025641024,0.016025641025641024,0.5826923076923076,1.0371794769230767,0.632051282051282,0.03205128205128205,0.6269230769230769,1.954678654615384,4.053213448717948,0.13964369015384617,0.17041292092307694,0.01282051282051282,0.0,0.0,0.01282051282051282,0.0,0.0,0.0,0.005128205128205128,0.026282051282051314,3.9775641358974365,0.03910256410256413,0.06987179487179489,0.015384615384615385,0.0,0.020512820512820513,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.023717948717948717,0.023717948717948717,0.0391025641025641,0.023717948717948717,0.08012820512820512,0.08012820512820512,2.1365384717948714,0.13653846153846155,0.0,0.0,0.0,0.11282051538461535,3.7493589666666676,3.023717948717948,1.6621794358974358,0.38525641025641033,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.005128205128205128,0.0,0.005128205128205128,0.0,0.0,0.0,0.002564102564102564,0.022435897435897436,0.10705128205128205,0.027564102564102563,0.025,0.0,0.0,0.0,0.005128205128205128,0.0,0.0,0.0,0.005128205128205128,0.0,0.038461538461538464,0.002564102564102564,0.007692307692307692,0.10740563846153849,3.4102139307692303,0.11600042564102563,0.10740563846153849,0.07307692307692307,0.2705128307692307,0.17051282307692303,0.07564102564102564,0.8249999761538465,43.05320479487179,7.753205132564103,0.33012820692307726,0.050641025641025635,1.4839743589743588,0.3096153846153846,0.06858974358974358,0.010256410256410256,0.0,0.005128205128205128,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.06474358974358974,0.06474358974358974,0.06474358974358974,0.06474358974358974,0.0,0.4615384615384615,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.009615384615384616,0.009615384615384616,0.2762820512820513,0.2711538461538462,0.04358974358974359,0.01282051282051282,0.002564102564102564,0.002564102564102564,0.0,0.0,0.0,0.0,0.0,0.02564102564102564,0.0,0.0,0.35384615384615387,0.046153846153846156,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.015384615384615384,0.09230769230769231,0.0,0.16923076923076924,0.04358974358974359,0.0641025641025641,0.0,0.0,0.11538461538461538,0.10256410256410256,0.0,1.574358974358974,5.880641017948719,0.9493589743589744,10.04474363333333,0.8688461533333331,0.010256410256410256,0.005128205128205128,0.0,0.0,0.49287545538461536,18.803937728205128,3.4626190553846143,0.3610805861538461,0.017948717948717947,0.4923076923076923,0.0,0.0,0.005128205128205128,0.0,0.3205128205128206,0.03333333333333333,1.1673076923076922,5.223717976923076,0.11602564102564104,0.11089743589743595,0.005128205128205128,0.0,0.0,0.0,0.0,0.020512820512820513,0.0,0.0,0.0,0.0,0.0,0.0,0.005128205128205128,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.5256410256410257,0.0,0.0,0.003205128205128205,0.003205128205128205,0.008333333333333333,0.1032051282051282,0.0,0.0,0.0,0.0,0.20213675282051283,0.6303418810256409,1.1414529974358971,3.8491453256410253,5.880442891025641,0.26044289094871803,0.23212121171794878,0.27571095530769235,0.005128205128205128,0.0,0.0,0.0,0.0,0.24358974358974358,0.05128205128205128,0.005128205128205128,0.11474358974358977,0.11474358974358977,0.11474358974358977,3.6198717999999994,4.239993310256409,0.2806859794871795,0.14991674871794877,0.1550449538461539,1.8108669146153846,9.751587184615383,4.380525015384615,1.018559222307692,0.05128205128205129,0.14615384615384616,0.01282051282051282,0.0,0.01282051282051282,0.005128205128205128,0.0,0.005128205128205128,0.0,0.1282051282051282,0.0,0.010256410256410256,0.005128205128205128,0.0,0.0,0.002564102564102564,0.515688258974359,0.515688258974359,1.0417566358974357,14.931995166666667,9.302732843589748,0.3426788141025641,0.32985830128205135,0.3811403525641025,0.0,0.005128205128205128,0.0,0.0,0.18453666153846154,0.18966486666666668,0.7832321230769228,6.429745943589742,11.533333294871797,1.8521870512820509,0.8328808474358972,0.7149321294871793,0.049358974358974364,0.010897435897435897,0.016025641025641024,0.010897435897435897]\",\"MP\":\"20\",\"IM\":\"0.029827238885660367\",\"QSIG\":\"[0.000, 0.000]\",\"start\":\"\\\"2020-06-30 08:00:00\\\"\",\"F0\":\"1.0320438036157227\",\"ES\":\"[23.8, 23.2, 33.7, 53, 66.6, 78.9, 122.3, 113.9, 90.8, 62.9, 46.2, 34.1]\",\"QSP\":\"0.000\",\"CS\":\"0.8968975627059064\",\"q\":\"[]\",\"LAG\":\"19.75125860965323\",\"QXSIG\":\"[0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000]\",\"runoffSim\":\"[]\",\"clen\":\"6\",\"FC\":\"0.47517949843757346\"}";
        Map data = JSON.parseObject(a, Map.class);
        SHANNXI obj = new SHANNXI(data);
        System.out.println(obj.predict());
    }
}
